﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Collections;
using VDataAdapter.BlockingQueue;
using System.Threading;
using VDataAdapter.ClientServer;

namespace VDataAdapter
{
    /// <summary>
    /// Handle Vdata Client request
    /// Everytime receive reset seq (seq = 1) or missing seq or any problem:
    /// Reset PsAdapter Thread to start sending again
    /// 
    /// </summary>
    public class VdataRequestHandler
    {
        protected TcpClient _vdataClient;
        protected ArrayList _memHistories;

        /// <summary>
        /// Interface between the 2: PsAdapterThread write message here and it'll be send to vdata
        /// </summary>
        protected CommunicationDataQueue _qMain;
        protected PSAdapterThread _psAdapaterThread;
        protected VDataClientThread _clientThread;

        public VdataRequestHandler()
        {            
            _memHistories = new ArrayList();
            _qMain = new CommunicationDataQueue();
        }

        /// <summary>
        /// Connect to price server and get all prices
        /// </summary>
        /// <param name="resetEvent"></param>
        /// <param name="qMain"></param>
        protected PSAdapterThread StartNewPushPriceThread(ManualResetEvent resetEvent, CommunicationDataQueue qMain)
        {            
            PSAdapterThread psAdapaterThread = new PSAdapterThread(resetEvent, qMain);
            resetEvent.Set();
            psAdapaterThread.Start();
            return psAdapaterThread;
        }

        protected VDataClientThread StartNewQueueSender(TcpClient clientSocket, CommunicationDataQueue qMain, ArrayList memHistories)
        {
            VDataClientThread clientThread = new VDataClientThread(clientSocket, qMain, memHistories);
            Thread thread = new Thread(new ThreadStart(clientThread.Start));
            thread.Start();
            Console.WriteLine("VdataClientRunning in Thread: " + thread.ManagedThreadId);
            return clientThread;
        }

        protected void StopPriceReceiver(PSAdapterThread psAdapter)
        {
            psAdapter.Unsubcribes();            
        }
 
        /// <summary>
        /// Start pushing messages to Vdata Tcp
        /// </summary>
        public void ReceiveNewClient(TcpClient clientSocket, ManualResetEvent resetEvent)
        {
            _clientThread = StartNewQueueSender(clientSocket, _qMain, _memHistories);            
            
            // polling for reload data seq = 1
            bool polling = true;
            while (polling)
            {
                if (_clientThread.IsReloadData)
                {
                    polling = false;
                    Console.WriteLine(">> Reset Price Server service data because seq = 1");
                    ResetPSAdapterThread(resetEvent);
                }
                else
                {
                    // no else because psAdapterThread should be already running
                }

                Thread.Sleep(200);
            } 
        }

        private void ResetPSAdapterThread(ManualResetEvent resetEvent)
        {
            if (_psAdapaterThread != null)
            {
                StopPriceReceiver(_psAdapaterThread);
                Program.bSocketConnectionKeeping = true;
            }
            _psAdapaterThread = StartNewPushPriceThread(resetEvent, _qMain);
        }


    }
}
